If the display name for the mail application includes .app, as happens if the finder...
[adiumx.git] / Plugins / Purple Service / ESPurpleNotifyEmailController.m
blob67d2de187315c253cdc66d8c687919b74ce8980c
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import "ESPurpleNotifyEmailController.h"
18 #import <AdiumLibpurple/SLPurpleCocoaAdapter.h>
19 #import <AdiumLibpurple/PurpleCommon.h>
20 #import <Adium/ESTextAndButtonsWindowController.h>
21 #import <Adium/AIContactAlertsControllerProtocol.h>
22 #import <Adium/AIAccount.h>
23 #import <AIUtilities/AIObjectAdditions.h>
25 @interface ESPurpleNotifyEmailController (PRIVATE)
26 + (void)openURLString:(NSString *)urlString;
27 + (void)startMailApplication;
28 + (NSString *)mailApplicationName;
29 @end
31 @implementation ESPurpleNotifyEmailController
33 /*!
34  * @brief Handle the notification of emails
35  *
36  * This may be called from the purple thread.
37  */
38 + (void *)handleNotifyEmailsForAccount:(AIAccount *)account count:(size_t)count detailed:(BOOL)detailed subjects:(const char **)subjects froms:(const char **)froms tos:(const char **)tos urls:(const char **)urls
40         NSFontManager                           *fontManager = [NSFontManager sharedFontManager];
41         NSFont                                          *messageFont = [NSFont messageFontOfSize:11];
42         NSMutableParagraphStyle         *centeredParagraphStyle;
43         NSMutableAttributedString   *message;
44         
45         centeredParagraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
46         [centeredParagraphStyle setAlignment:NSCenterTextAlignment];
47         message = [[NSMutableAttributedString alloc] init];
48         
49         //Title
50         NSString                *title;
51         NSFont                  *titleFont;
52         NSDictionary    *titleAttributes;
53         
54         title = AILocalizedString(@"You have mail!\n",nil);
55         titleFont = [fontManager convertFont:[NSFont messageFontOfSize:12]
56                                                          toHaveTrait:NSBoldFontMask];
57         titleAttributes = [NSDictionary dictionaryWithObjectsAndKeys:titleFont,NSFontAttributeName,
58                 centeredParagraphStyle,NSParagraphStyleAttributeName,nil];
59         
60         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:title
61                                                                                                                                          attributes:titleAttributes] autorelease]];
62         
63         //Message
64         NSString                *numberMessage;
65         NSDictionary    *numberMessageAttributes;
66         NSString                *yourName;
67         
68         if (account) {
69                 yourName = [account formattedUID];
70         } else if (tos && *tos) {
71                 yourName = [NSString stringWithUTF8String:*tos];
72         } else {
73                 yourName = nil;
74         }
76         if (yourName && [yourName length]) {
77                 numberMessage = ((count == 1) ? 
78                                                  [NSString stringWithFormat:AILocalizedString(@"%@ has 1 new message.",nil), yourName] :
79                                                  [NSString stringWithFormat:AILocalizedString(@"%@ has %u new messages.",nil), yourName, count]);
81         } else {
82                 numberMessage = ((count == 1) ? 
83                                                  AILocalizedString(@"You have 1 new message.",nil) :
84                                                  [NSString stringWithFormat:AILocalizedString(@"You have %u new messages.",nil), count]);               
85         }
87         numberMessageAttributes = [NSDictionary dictionaryWithObjectsAndKeys:messageFont,NSFontAttributeName,
88                 centeredParagraphStyle,NSParagraphStyleAttributeName,nil];
89         
90         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:numberMessage
91                                                                                                                                          attributes:numberMessageAttributes] autorelease]];
92         
93         if (count == 1) {
94                 BOOL    haveFroms    = (froms    != NULL);
95                 BOOL    haveSubjects = (subjects != NULL);
96                 
97                 if (haveFroms || haveSubjects) {
98                         NSFont                  *fieldFont;
99                         NSDictionary    *fieldAttributed, *infoAttributed;
100                         
101                         fieldFont =  [fontManager convertFont:messageFont
102                                                                           toHaveTrait:NSBoldFontMask];
103                         fieldAttributed = [NSDictionary dictionaryWithObject:fieldFont forKey:NSFontAttributeName];
104                         infoAttributed = [NSDictionary dictionaryWithObject:messageFont forKey:NSFontAttributeName];
105                         
106                         //Skip a line
107                         [[message mutableString] appendString:@"\n\n"];
108                         
109                         if (haveFroms) {
110                                 NSString        *fromString = [NSString stringWithUTF8String:(*froms)];
111                                 if (fromString && [fromString length]) {
112                                         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:AILocalizedString(@"From: ",nil)
113                                                                                                                                                                          attributes:fieldAttributed] autorelease]];
114                                         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:fromString
115                                                                                                                                                                          attributes:infoAttributed] autorelease]];
116                                 }
117                         }
118                         
119                         if (haveFroms && haveSubjects) {
120                                 [[message mutableString] appendString:@"\n"];
121                         }
122                         
123                         if (haveSubjects) {
124                                 NSString        *subjectString = [NSString stringWithUTF8String:(*subjects)];
125                                 if (subjectString && [subjectString length]) {
126                                         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:AILocalizedString(@"Subject: ",nil)
127                                                                                                                                                                          attributes:fieldAttributed] autorelease]];
128                                         AILog(@"%@: %@ appending %@",self,message,subjectString);
129                                         [message appendAttributedString:[[[NSAttributedString alloc] initWithString:subjectString
130                                                                                                                                                                          attributes:infoAttributed] autorelease]];                              
131                                 } else {
132                                         AILog(@"Got an invalid subjectString from %s",*subjects);
133                                 }
134                         }
135                 }
136         }
137         
138         NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:title,@"Title",
139                 message,@"Message",nil];
140         
141         NSString        *urlString = (urls ? [NSString stringWithUTF8String:urls[0]] : nil);
143         if (urlString) {
144                 [infoDict setObject:urlString forKey:@"URL"];
145         }
146         
147         [self mainPerformSelector:@selector(showNotifyEmailWindowForAccount:withMessage:URLString:)
148                                    withObject:account
149                                    withObject:message
150                                    withObject:(urlString ? urlString : nil)];
152         [centeredParagraphStyle release];
153         [message release];
154         
155         return NULL;
159  * @brief Show the New Mail message
161  * Displays the New Mail message, optionally offerring an Open Mail button (if a URL to open the webmail is passed).
163  * @param account The account which received new mail
164  * @param inMessage An attributed message describing the new mail
165  * @param inURLString The URL to the appropriate webmail, or nil if no webmail link is available
166  */
167 + (void)showNotifyEmailWindowForAccount:(AIAccount *)account withMessage:(NSAttributedString *)inMessage URLString:(NSString *)inURLString
168 {       
169         NSString *mailApplicationName = [self mailApplicationName];
170         [ESTextAndButtonsWindowController showTextAndButtonsWindowWithTitle:AILocalizedString(@"New Mail",nil)
171                                                                                                                   defaultButton:nil
172                                                                                                                 alternateButton:(inURLString ? 
173                                                                                                                                                  AILocalizedString(@"Open Mail in Browser",nil) :
174                                                                                                                                                  nil)
175                                                                                                                         otherButton:((mailApplicationName && [mailApplicationName length]) ?
176                                                                                                                                                  [NSString stringWithFormat:AILocalizedString(@"Launch %@", nil), mailApplicationName] :
177                                                                                                                                                  nil)
178                                                                                                                            onWindow:nil
179                                                                                                           withMessageHeader:nil
180                                                                                                                          andMessage:inMessage
181                                                                                                                                  target:self
182                                                                                                                            userInfo:inURLString];       
183         
184         //XXX - Hook this to the account for listobject
185         [[[AIObject sharedAdiumInstance] contactAlertsController] generateEvent:ACCOUNT_RECEIVED_EMAIL
186                                                                                                                           forListObject:account
187                                                                                                                                    userInfo:[inMessage string]
188                                                                                            previouslyPerformedActionIDs:nil];   
192  * @brief Window was closed, either by a button being clicked or the user closing it
193  */
194 + (BOOL)textAndButtonsWindowDidEnd:(NSWindow *)window returnCode:(AITextAndButtonsReturnCode)returnCode userInfo:(id)userInfo
196         switch (returnCode) {
197                 case AITextAndButtonsAlternateReturn:
198                         if (userInfo) [self openURLString:userInfo];
199                         break;
201                 case AITextAndButtonsDefaultReturn:
202                         break;
203                         
204                 case AITextAndButtonsOtherReturn:
205                         if (userInfo) [self startMailApplication];
206                         break;
207                         
208                 case AITextAndButtonsClosedWithoutResponse:
209                         //No action needed
210                         break;
211         }
212         
213         return YES;
217  * @brief Start mail application from the new mail window
219  * Launch the user's mail application instead of opening the webmail-page
220  */ 
221 + (void)startMailApplication {
222         if ([[NSWorkspace sharedWorkspace] launchApplication:[self mailApplicationName]] == NO) {
223                 NSLog(@"Could not launch mail application '%@'", [self mailApplicationName]);
224         }
228  * @brief Open a URL string from the open mail window
230  * The urlString could either be a web address or a path to a local HTML file we are supposed to load.
231  * The local HTML file will be in the user's temp directory, which Purple obtains with g_get_tmp_dir()...  
232  * so we will, too.
233  */ 
234 + (void)openURLString:(NSString *)urlString
236         if ([urlString rangeOfString:[NSString stringWithUTF8String:g_get_tmp_dir()]].location != NSNotFound) {
237                 //Local HTML file
238                 CFURLRef        appURL = NULL;
239                 OSStatus        err;
240                 
241                 /* Obtain the default http:// handler. We don't care what would handle _this file_ (its extension doesn't matter)
242                  * nor what normally happens when the user opens a .html file since that is, on many systems, an HTML editor.
243                  * Instead, we want to know what application to use for viewing web pages... and then open this file in it.
244                  */
245                 err = LSGetApplicationForURL((CFURLRef)[NSURL URLWithString:@"http://www.adiumx.com"],
246                                                                          kLSRolesViewer,
247                                                                          /*outAppRef*/ NULL,
248                                                                          &appURL);
249                 if (err == noErr) {
250                         [[NSWorkspace sharedWorkspace] openFile:[urlString stringByExpandingTildeInPath]
251                                                                         withApplication:[(NSURL *)appURL path]];
252                 } else {
253                         NSURL           *url;
254                         
255                         //Web address
256                         url = [NSURL URLWithString:urlString];
257                         [[NSWorkspace sharedWorkspace] openURL:url];
258                 }
259                 
260                 if (appURL) {
261                         //LSGetApplicationForURL() requires us to release the appURL when we are done with it
262                         CFRelease(appURL);
263                 }
264                 
265         } else {
266                 NSURL           *emailURL;
267                 
268                 //Web address
269                 emailURL = [NSURL URLWithString:urlString];
270                 [[NSWorkspace sharedWorkspace] openURL:emailURL];
271         }
275  * @brief Returns the name of the user's mail application
277  * Use the LaunchServices to identify the user's mail application and return it's name
278  * @return NSString with the application's name
279  */ 
280 + (NSString *)mailApplicationName {
281         NSString *appName;
282         FSRef myAppRef;
283         
284         LSGetApplicationForURL((CFURLRef)[NSURL URLWithString:@"mailto://"], kLSRolesAll, &myAppRef, NULL);
285         LSCopyDisplayNameForRef(&myAppRef, (CFStringRef *)&appName);
286         
287         NSRange appRange;
288         if ((appRange = [appName rangeOfString:@".app" options:(NSCaseInsensitiveSearch | NSBackwardsSearch | NSAnchoredSearch)]).location != NSNotFound) {
289                 appName = [[appName substringToIndex:appRange.location] retain];
290         }
292         return [appName autorelease];
295 @end